#!/bin/bash -e
#
#   Neutron3529's Unity Game Plugin
#   Copyright (C) 2022 Neutron3529
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as
#   published by the Free Software Foundation, either version 3 of the
#   License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
############################################################################
#
#   * compile instructions: put this file and `utils.cs` in `steamapps`
#   * folder, open a terminal in the same folder, and execute:
#   *
#   * ```
#   *     chmod +x ${file}.cs
#   *     ./${file}.cs
#   * ```
#   *
#   * then the mod will be compiled automatically.
#   *
#   * Here we wrote a shebang like file, which is correct
#   * in my computer (Manjaro XFCE), if such script do not work
#   * in your computer, you could just try the instructions below :

export GAME_NAME="${0%\.cs}"                                # might modify if the name mismatch.
export GAME_DIR="WulinSH"                                # might be modified, but "$GAME_NAME" cover most of the cases.

export FILE_NAME="$0"
export ASSEMBLY="Assembly-CSharp"                           # might be modified
export UTILS="utils.cs"                                     # might be modified if you do not put utils.cs in the current dir.
export PLUGIN_ID="Neutron3529.Cheat"                        # should be modified
export NAMESPACE_ID="Neutron3529.Cheat"                     # should be modified
export GAME_BASE_DIR="common/$GAME_DIR"                     # should modify GAME_DIR instead since GAME_DIR == GAME_NAME is almost always true.

export IFS=$'\n' # to disable the annoying space.
export DOTNET="dotnet" # the location of the DOTNET executable file.
[ -z "$DOTNET_CSC_DLL" ] && export DOTNET_CSC_DLL=`\ls /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll` # In manjaro, the csc.dll is located in /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll

case $1 in
V)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
v)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
VERBOSE) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
verbose) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
D)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
d)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
DEBUG)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
debug)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
*)       EXTRA_DEFINE=""                                               ;;
esac

_MODE__SELECT_=100
( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_) | sed s/%%NAMESPACE_ID%%/${NAMESPACE_ID}/g | sed s/%%PLUGIN_ID%%/${PLUGIN_ID}/g | $DOTNET $DOTNET_CSC_DLL -nologo -t:library \
-r:"${GAME_BASE_DIR}/BepInEx/core/0Harmony.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.Core.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.Unity.IL2CPP.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/core/Il2CppInterop.Runtime.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/interop/Il2Cppmscorlib.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/interop/Il2CppSystem.Core.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/interop/UnityEngine.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/interop/UnityEngine.UI.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/interop/UnityEngine.CoreModule.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/interop/ModShare.Runtime.dll" \
-r:"${GAME_BASE_DIR}/BepInEx/interop/GamePlugins.InspectorEnhance.Runtime.dll" \
$(for i in "${GAME_BASE_DIR}/BepInEx/interop/$ASSEMBLY"*.dll ; do echo -e "-r:\"$i\"\n" ; done) \
`[ -e "${GAME_BASE_DIR}/dotnet/netstandard.dll" ] && echo "-r:\"${GAME_BASE_DIR}/dotnet/netstandard.dll\""` \
-r:"${GAME_BASE_DIR}/dotnet/System.dll" \
-r:"${GAME_BASE_DIR}/dotnet/System.Runtime.dll" \
-r:"${GAME_BASE_DIR}/dotnet/System.Private.CoreLib.dll" \
-r:"${GAME_BASE_DIR}/dotnet/mscorlib.dll" \
-out:"${GAME_BASE_DIR}/BepInEx/plugins/${FILE_NAME%.*}".dll \
-optimize $EXTRA_DEFINE \
- $UTILS && rm -f "${GAME_BASE_DIR}/BepInEx/config/${PLUGIN_ID}.cfg";

if [ -n "$2" ]; then
    git add ${FILE_NAME}
    case $2 in
    R) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
r) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
RANDOM) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
random) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
U) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
u) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
UPLOAD) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
upload) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
*) git commit -am "$2" ;;
esac
git push
fi
exit


using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;

using BepInEx;
using BepInEx.Unity.IL2CPP;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

namespace %%NAMESPACE_ID%%;

[BepInPlugin("%%PLUGIN_ID%%", "%%NAMESPACE_ID%%", "0.1.0")]
public class Cheat : Neutron3529.ModEntry {
    public Cheat() : base("%%PLUGIN_ID%%") {}
    public override void Awake() {
        base.Awake();
        // Mafi.Localization.LocalizationManager.EnableLocalization(); // 不知道为什么不加这一句会导致游戏变成纯英文
        // 主要逻辑放在`utils.cs`中，这里的Awake2只是为了以防万一
        // 目前来说，这个函数的唯一用途是用来“叮”……
        // 就像这样：
        var traits=BaseDataClass.GetGameData<GameData.TraitDataScriptObject>().TraitData;
        foreach(var trait in traits){
            var td=trait;
            td.TraitPointCost=0;
            td.IsUseByPlayer=true;
        }
        var mines=BaseDataClass.GetGameData<GameData.MiningDataScriptObject>().MiningData;
        foreach(var mine in mines){
            if(MiningConsts.amount>0)mine.MiningMaxNum=MiningConsts.amount; // 采集点重复采集次数
            if(MiningConsts.speed>1f)mine.FrameTime/=MiningConsts.speed; // 采集速度(?)
            if(MiningConsts.speed>1f)mine.MaxTime/=MiningConsts.speed; // 采集速度(?)
        }
        var mbs=BaseDataClass.GetGameData<GameData.MiningBatchDataScriptObject>().MiningBatchData;
        foreach(var mine in mbs){
            if(MiningConsts.amount>0)mine.MiningMaxNum=MiningConsts.amount; // 采集点重复采集次数
            if(MiningConsts.speed>1f)mine.FrameTime/=MiningConsts.speed; // 采集速度(?)
        }
        if(ForgeConsts.lmul!=0 || ForgeConsts.umul>0 || ForgeConsts.dlmul!=0 || ForgeConsts.dumul>0){
            var ifds=BaseDataClass.GetGameData<GameData.ItemForgeEffectDataScriptObject>().ItemForgeEffectData;
            foreach(var ifd in ifds){
                if(ifd.BonusExt!=null){
                    // logger($"{ifd.BonusExt.key}(valid:{ifd.BonusExt.isValid})");
                    // foreach(var val in ifd.BonusExt.values){
                    //     logger($"val:{val}"); // int
                    // }
                    // foreach(var val in ifd.BonusExt.dValues){
                    //     logger($"dval:{val}"); // decimal
                    // }
                    for(int i=0;i<ifd.BonusExt.values.Count;i+=2){
                        if(ForgeConsts.lmul!=0){
                            if(ForgeConsts.lmul>0){
                                ifd.BonusExt.values[i]=(int)((double)ifd.BonusExt.values[i]*ForgeConsts.lmul);
                            } else {
                                ifd.BonusExt.values[i]=(int)-((double)ifd.BonusExt.values[i+1]*ForgeConsts.lmul);
                            }
                        }
                        if(ForgeConsts.umul>0){
                            ifd.BonusExt.values[i+1]=(int)(ifd.BonusExt.values[i+1]*ForgeConsts.umul);
                        }
                    }
                    for(int i=0;i<ifd.BonusExt.dValues.Count;i+=2){
                        if(ForgeConsts.dlmul!=0){
                            if(ForgeConsts.dlmul>0){
                                ifd.BonusExt.dValues[i]*=(Il2CppSystem.Decimal)ForgeConsts.dlmul;
                            } else {
                                ifd.BonusExt.dValues[i]=-ifd.BonusExt.dValues[i+1]*(Il2CppSystem.Decimal)ForgeConsts.dlmul;
                            }
                        }
                        if(ForgeConsts.dumul>0){
                            ifd.BonusExt.dValues[i+1]*=(Il2CppSystem.Decimal)ForgeConsts.dumul;
                        }
                    }
                }
            }
            logger("武器制造-上下限修改结束");
        }
        logger("叮~修改器启动，请安心游戏");
    }
    public class ForgeConsts : Const {
        [Desc("武器制造-下限乘数-为0禁用，为负数则使用原始的上限值成这个数字的绝对值")]
        public static double lmul=-1.0;
        [Desc("武器制造-下限乘数-decimal-为0禁用，为负数则使用原始的上限值成这个数字的绝对值")]
        public static double dlmul=-1.0;
        [Desc("武器制造-上限乘数，非正数时禁用此patch")]
        public static double umul=0.0;
        [Desc("武器制造-上限乘数-decimal-非正数时禁用此patch")]
        public static double dumul=0.0;
    }
    [Desc("在成就界面开启全成就",-1)]
    public class FullAchievement : Entry {
        [HarmonyPatch(typeof(WuLin.AchievementUI),"Start")]
        public static void Prefix(){
            var ads=BaseDataClass.GetGameData<GameData.AchievementDataScriptObject>();
            var achman=MonoSingleton<WuLin.AchievementManager>.Instance;
            foreach(var id in ads.data.Keys){
                if(!achman.IsComplated(id)){achman.Complate(id);}
            }
            achman.ReportSteamRefresh();
        }
    }
    [Desc("说鸡需带八，文明靠大家")]
    [HarmonyPatch(typeof(WuLin.GameUtil), "ContainsForbiddenWord")]
    public class AllowFword : Entry {
        // public static int val;public void Init() {base.Init(ref val);}
        public static bool Prefix(ref bool __result){
            return __result=false;
        }
    }

    [Desc("凭什么只有NPC技能不消耗EP啊",-1)]
    [HarmonyPatch(typeof(WuLin.BattleActor.BattleActorProp), "CostEp")]
    public class BattleActorPropCostEp:Entry{
        // public static int val;public void Init() {base.Init(ref val);}
        public static void Prefix(ref int amount){
            amount=0;
        }
    }
    [Desc("我们不是偷，我们是侠盗！")]
    public class StealManager:Entry{
        // public static int val;public void Init() {base.Init(ref val);}
        [HarmonyPrefix, HarmonyPatch(typeof(WuLin.StealManager), "Steal")]
        public static void Prefix0(WuLin.StealManager __instance){
            if(__instance.RangePar<10000){__instance.RangePar=10000;}
            if((double)__instance.SpeedPar>0.1){__instance.SpeedPar=(Il2CppSystem.Decimal)0.1;}
        }
        // [HarmonyPrefix, HarmonyPatch(typeof(WuLin.StealthManager), "TryAddPercepter")]
        // public static bool Prefix1(){
        //     return false;
        // } // 此时潜行没办法把人勾走
        [HarmonyPostfix, HarmonyPatch(typeof(WuLin.StealthManager), "GetPerceptionSpeed")]
        public static void Postfix0(ref float __result){
            __result*=0.1f;
        }
    }
    [Desc("难道把湛蓝碧绿的毒液倒入被害者的口中也会有成功率这一说吗？"), HarmonyPatch(typeof(WuLin.PoisionManager), "Poision")]
    public class PoisionManagerPoision:Entry{
        // public static int val;public void Init() {base.Init(ref val);}
        public static void Prefix(WuLin.PoisionManager __instance){
            if(__instance.RangePar<10000){__instance.RangePar=10000;}
            if((double)__instance.SpeedPar>0.1){__instance.SpeedPar=(Il2CppSystem.Decimal)0.1;}
        }
    }
    [Desc("难道出千的意思不是只要我出，就算我赢吗？")]
    public class UISicBoCheat:Entry{
        [HarmonyPatch(typeof(WuLin.UISicBo), "Cheat")]
        public static void Prefix(WuLin.UISicBo __instance){
            __instance.CheatNeedEp=0;
            logger($"BigStartCount {WuLin.UISicBo.BigStartCount} curPlayerBetType {__instance.curPlayerBetType}");
        }
        [HarmonyPatch(typeof(WuLin.UISicBo), "Settle")]
        public static void Prefix(WuLin.UISicBo __instance, WuLin.SicBoRole role, Dictionary<SicBoBetType, int> resultRatioDict){
            var sum=0L;
            foreach(var x in role.CurRoundBetDict.Values){
                sum+=x;
            }
            bool flag=role.Type==WuLin.SicBoRoleType.Player;
            if(flag){
                logger("Player found.");
                if(role.CharacterInstance!=null){
                    logger($"main={role.CharacterInstance.IsMainCharacter}, char {role.CharacterInstance.FullName} found");
                    foreach(var kv in resultRatioDict){
                        logger($"result: {kv.Key}:{kv.Value}");
                    }
                } else {
                    flag=false;
                    logger("player nobody occurs!");
                }
            } else {
                if(role.CharacterInstance.IsMainCharacter){
                    logger($"mainchar {role.CharacterInstance.FullName} found");
                }else{
                    logger($"nobody settlement.");
                }
            }
            if(flag){
                foreach(var x in resultRatioDict.Keys){
                    if(x==SicBoBetType.Big || x==SicBoBetType.Small){
                        role.CurRoundBetDict[x]=sum;
                        break;
                    }
                }
            } else {
                role.CurRoundBetDict.Clear();
                role.CurRoundBetDict[SicBoBetType.One]=sum;
            }
        }
    }
    [Desc("真正的刺客从来都是正面硬上的"), HarmonyPatch(typeof(WuLin.AssassinManager), "Assassin")]
    public class AssassinManagerAssassin:Entry{
        public static void Prefix(WuLin.AssassinManager __instance){
            if(__instance.RangePar<10000){__instance.RangePar=10000;}
            if((double)__instance.SpeedPar>0.1){__instance.SpeedPar=(Il2CppSystem.Decimal)0.1;}
        }
    }
    [Desc("不会点穴，拿刀架在人家脖子上，人家也会保持一动不动的"), HarmonyPatch(typeof(ParalyzeManager), "Paralyze")]
    public class ParalyzeManagerParalyze:Entry{
        // public static int val;public void Init() {base.Init(ref val);}
        public static void Prefix(ParalyzeManager __instance){
            if(__instance.RangePar<10000){__instance.RangePar=10000;}
            if((double)__instance.SpeedPar>0.1){__instance.SpeedPar=(Il2CppSystem.Decimal)0.1;}
        }
    }
    public class MiningConsts : Const {
        [Desc("资源点采集数量")]
        public static int amount=100;
        [Desc("资源点采集速度")]
        public static float speed=10f;
    }
    [Desc("资源点均可视为丁级资源点（因而更容易采集）")]
    public class MiningBatchUIUpdateToolCount:Entry{
        [HarmonyPrefix, HarmonyPatch(typeof(WuLin.MiningBatchUI), "UpdateLevel")]
        public static void pf(WuLin.MiningBatchUI __instance){
            // logger("Mining:"+__instance.tableData.Level+" "+__instance.tableData.MiningMaxNum+" "+__instance.tableData.RevertTime+" "+__instance.tableData.StrExp);
            // logger("Mining:"+__instance.tableData.CostItem[0]+" "+__instance.tableData.CostItem[1]+" "+__instance.tableData.CostItem[2]+" "+__instance.tableData.CostItem[3]);
            // logger("Mining:"+__instance.tableData.DropItem[0]+" "+__instance.tableData.DropItem[1]+" "+__instance.tableData.DropItem[2]+" "+__instance.tableData.DropItem[3]); -3个1组，需要更多分析。
            // __instance.tableData.StrExp=1000;
            __instance.tableData.Level=0; // 采集点资源
            // __instance.tableData.MiningMaxNum=500; // 采集点重复采集次数
            // __instance.tableData.FrameTime=0.01f; // 采集速度(?)
            __instance.tableData.RevertTime=1; // 采集点恢复时间
            // __instance.tableData.CostItem[3]=__instance.tableData.CostItem[2]=__instance.tableData.CostItem[1]=__instance.tableData.CostItem[0]; // 会导致玩家只能用最低等级的工具进行采集
        }
        // [HarmonyPrefix, HarmonyPatch(typeof(WuLin.MiningBatchUI), "PlayAni")] // 无效
        // public static void pfx(ref float frameTime){
        //     frameTime*=0.1f;
        // }
        // [HarmonyPrefix, HarmonyPatch(typeof(WuLin.MiningBatchUI), "UpdateMiningLess")] // 仅显示
        // public static bool prfx(){
        //     return false;
        // }
    }


    [HarmonyPatch(typeof(WuLin.GameCharacterInstance), "ChangeAdditionProp")]
    public class GameCharacterInstanceChangeAdditionProp_Thanks_Gmhaxxing:Entry{
        [Desc("人物能力经验乘数(感谢Gmhaxxing的代码)")]
        public static int val=10;
        public static void Prefix(string key, ref Decimal value) {
            if (key.Contains("能力经验_")) {
                value *= val;
            }
        }
    }


    // [Desc("口才什么的并不能代替黑幕的作用")]
    // public class FactionNpcFunctionDataAll:Entry{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     // static IEnumerable<MethodBase> TargetMethods(){
    //     //     // HarmonyPatch(typeof(WuLin.FactionNpcFunctionData), "init")
    //     //     // HarmonyPatch(typeof(WuLin.FactionNpcFunctionData), "OnEnable")
    //     //     // ...
    //     //     foreach(MethodInfo m in typeof(WuLin.FactionNpcFunctionData).GetMethods((BindingFlags)(-1))){
    //     //         if(m.Name.Length<4 || (m.Name[1]!='e' && m.Name[2]!='t' && m.Name[3]!='_' && (m.Name[0]!='g' || m.Name[0]!='s' )) ) {
    //     //             logger("注入WuLin.FactionNpcFunctionData的"+m.Name+"方法");
    //     //             yield return m;
    //     //         }
    //     //     }
    //     // }
    //     [HarmonyPatch(typeof(WuLin.FactionNpcFunctionData), "OnEnable")]
    //     public static void Prefix(WuLin.FactionNpcFunctionData __instance){
    //         __instance.helloCD=1;
    //         __instance.relationGreetingCD=1;
    //         __instance.relationGreetingFaction=10;
    //         __instance.relationGreetingFactionMax=100;
    //         __instance.relationGreetingNpc=10;
    //         __instance.relationGreetingNpcMax=100;
    //     }
    // }

    // [Desc("假装拥有全部DLC")]
    // [HarmonyPatch(typeof(ndemic.game.App), "CheckDLCUnlocked")]
    // public class AppCheckDLCUnlocked:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static bool Prefix(ref bool __result){__result=true;return false;}
    // }
    // [Desc("你可以试试锁定一个特性-锁定初始人物特性时修改特性数量，物品数量，可用点数上限")]
    // [HarmonyPatch(typeof(WuLin.PlayerCreateManager), "LockTraitByIndex")]
    // public class PlayerCreateManagerLockTraitByIndex:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static void Prefix(WuLin.PlayerCreateManager __instance, int index){
    //         __instance.maxSelectableAbility=25;
    //         __instance.maxSelectableItems=100;
    //         __instance.maxSelectableTrait=10;
    //         __instance.mainPropPoint=45;
    //         // var c=__instance.selectableAbility.GetEnumerator();while (c.MoveNext()) { logger(__instance.selectableAbility.GetEnumerator().Current); }
    //         // __instance.selectableTraitDatas.ForEach((Action<GameData.TraitData>)PlayerCreateManagerCreateTraits.log);
    //     }
    // }
    // [Desc("解除锁定特性时将此特性调整到首位")]
    // [HarmonyPatch(typeof(WuLin.PlayerCreateManager), "LockTraitByIndex")]
    // public class PlayerCreateManagerLockTraitByIndex_Unlock:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static void Prefix(WuLin.PlayerCreateManager __instance, int index){
    //         if (index==-1) {
    //             if(__instance.lockedTraitIndex>0 && __instance.lockedTraitIndex<__instance.selectableTraitDatas.Count){
    //                 var c=__instance.selectableTraitDatas[0];
    //                 __instance.selectableTraitDatas[0]=__instance.selectableTraitDatas[__instance.lockedTraitIndex];
    //                 __instance.selectableTraitDatas[__instance.lockedTraitIndex]=c;
    //             }
    //         }
    //     }
    // }
    // [Desc("开局时拥有所有roll到的特性，并强制加入&忽略特性-开启此选项时不建议选择任何特性，因为这样会造成特性重复","无师自通|惺惺相惜|异性相吸|武林盟主|圣贤传人|气劲贯体|气场威压|绵里藏针|随手烟尘|真气护体|袖里青蛇|掌中带毒|金针刺穴|偃武息戈|来去飘忽|春燕回翔|疏而不漏|刀剑无眼|暴虐不仁|勇猛无挡|所向披靡|身形鬼魅|滚滚波涛|淬毒手段|势不可挡|毒蛊寄生|孟尝遗风|灵台清明|磨刀霍霍|暗劲激发|势大力沉|暗送无常|深究其理|如封似闭|雁过拔毛|武学奇才|杀意腾腾|嫉恶如仇|剑不空回|繁华楼主|飞燕凌波|医者自医|金枝玉叶|皇权特许&聪颖灵巧|福泽深厚|良才美玉|武林霸主|扮猪吃虎|邪魔外道")]
    // public class PlayerCreateManagerSortSelectedTraits:Bstring{
    //     public static string val;public void Init() {base.Init(ref val);}
    //     public static List<GameData.TraitData> tl=new List<GameData.TraitData>();
    //     public static HashSet<string> ts=new HashSet<string>();
    //     [HarmonyPostfix, HarmonyPatch(typeof(WuLin.PlayerCreateManager), "GenerateSelectabelTraits")]
    //     public static void Postfix0(WuLin.PlayerCreateManager __instance){
    //         if(ts.Add("")){
    //             var data=BaseDataClass.GetGameData<GameData.TraitDataScriptObject>().TraitData;
    //             foreach (var trait in data) {
    //                 logger(trait.GetName(true)+"("+trait.Rarity+","+trait.GenRate+","+trait.IsHidden()+"):"+trait.GetInfo());
    //             }
    //             {
    //                 HashSet<string> ml=new HashSet<string>();
    //                 foreach (var i in val.Split('&')[0].Split('|')){
    //                     ml.Add(i);
    //                 }
    //                 foreach (var trait in data) {
    //                     if(ml.Contains(trait.GetName(false))){
    //                         ts.Add(trait.GetName(true));
    //                         tl.Add(trait);
    //                     }
    //                 }
    //             }
    //             {
    //                 HashSet<string> nl=new HashSet<string>();
    //                 foreach (var i in val.Split('&')[1].Split('|')){
    //                     nl.Add(i);
    //                 }
    //                 foreach (var trait in data) {
    //                     if (nl.Contains(trait.GetName(false))){
    //                         ts.Add(trait.GetName(true));
    //                     }
    //                 }
    //             }
    //         }
    //         __instance.selectableTraitDatas.ForEach((Action<GameData.TraitData>)((trait)=>{if(ts.Add(trait.GetName(true))){
    //             tl.Add(trait);
    //         }}));
    //     }
    //     [HarmonyPostfix, HarmonyPatch(typeof(WuLin.PlayerCreateManager), "SortSelectedTraits")]
    //     public static void Postfix1(Il2CppSystem.Collections.Generic.List<GameData.TraitData> __result){
    //         // __result.Clear();
    //         foreach (var i in from trait in tl
    //                     orderby trait.Rarity descending, trait.GetName(false)
    //                     select trait){
    //             __result.Add(i);
    //         }
    //     }
    // }
    // [Desc("处理特性的稀有度")]
    // [HarmonyPatch(typeof(WuLin.PlayerCreateManager), "GenerateSelectabelTraits")]
    // public class PlayerCreateManagerGenerateSelectabelTraits_Div:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static void Prefix(WuLin.PlayerCreateManager __instance){
    //         // logger("gen CALLED");
    //         // logger("__instance.lockedTraitIndex="+__instance.lockedTraitIndex);
    //         // logger("traits:");
    //         // var maxRate=0f;
    //         __instance.selectableTraitDatas.ForEach((Action<GameData.TraitData>)((trait)=>{
    //             // logger(trait.GetName(true)+"("+trait.Rarity+","+trait.GenRate+"): "+trait.GetInfo());
    //             if(trait.Rarity<=3&& trait.GenRate>(float)1e-3)trait.GenRate*=(float)1e-5;
    //             if(trait.Rarity<=2&& trait.GenRate>(float)1e-8)trait.GenRate*=(float)1e-5;
    //             if(trait.Rarity<=1&& trait.GenRate>(float)1e-13)trait.GenRate*=(float)1e-5;
    //             // maxRate=Math.Max(maxRate,trait.GenRate);
    //         }));
    //         // logger("maxRate:"+maxRate);
    //     }
    // }
    // [Desc("处理特性的稀有度-白名单&黑名单，启用时需保证字符串有一个&符号。白名单中内容一经出现则不会消失，黑名单中内容只会出现一次","&财大气粗|影子护卫|草木皆兵&包括第二个`&`在内，其之后的全部内容可以看作注释。如果你想刷开局，可以把 骨骼清奇|身强体健|福泽深厚|龙精虎猛|良才美玉 填上，这些会让你的开局属性上限接近15点。")]
    // [HarmonyPatch(typeof(WuLin.PlayerCreateManager), "GenerateSelectabelTraits")]
    // public class PlayerCreateManagerGenerateSelectabelTraits_Block:Bstring{
    //     public static HashSet<string> hs;
    //     public static HashSet<string> bs;
    //     public static string val;public void Init() {
    //         base.Init(ref val);
    //         if (this.Met(val)){
    //             hs=new HashSet<string>();
    //             bs=new HashSet<string>();
    //             var hb=val.Split('&');
    //             foreach(var trait in hb[1].Split('|')){
    //                 hs.Add(trait);
    //             }
    //             foreach(var trait in hb[0].Split('|')){
    //                 bs.Add(trait);
    //             }
    //         }
    //     }
    //     public static void Prefix(WuLin.PlayerCreateManager __instance){
    //         // logger("exec bw");
    //         __instance.selectableTraitDatas.ForEach((Action<GameData.TraitData>)((trait)=>{
    //             if (hs.Contains(trait.GetName(false)) ) {
    //                 trait.GenRate=1e-30f;
    //             } else if (bs.Contains(trait.GetName(false)) ) {
    //                 trait.GenRate=1f;
    //             }
    //         }));
    //     }
    // }
    // [Desc("资源点均可视为丁级资源点（因而更容易采集）")]
    // [HarmonyPatch(typeof(GameData.MiningBatchData), "Level",MethodType.Getter)]
    // public class MiningBatchDataLevel:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static bool Prefix(ref int __result){
    //         __result=0;
    //         return false;
    //     }
    // }
    // [Desc("资源点可采集资源个数增加")]
    // [HarmonyPatch(typeof(GameData.MiningBatchData), "MiningMaxNum",MethodType.Getter)]
    // public class MiningBatchDataMiningMaxNum:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static bool Prefix(ref int __result){
    //         __result=250;
    //         return false;
    //     }
    // }
    // [Desc("资源点加速刷新")]
    // [HarmonyPatch(typeof(GameData.MiningBatchData), "RevertTime",MethodType.Getter)]
    // public class MiningBatchDataRevertTime:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static bool Prefix(ref int __result){
    //         __result=1;
    //         return false;
    //     }
    // }

    // [Desc("挖矿不消耗体力")]
    // [HarmonyPatch(typeof(WuLin.MiningBatchUI), "UpdateEnergy")]
    // public class MiningManagerUpdateEnergy:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static bool Prefix(){
    //         return false;
    //     }
    // }
    // [Desc("锁定特性的同时锁定此特性之上的全部特性-使用的是卑鄙的覆盖法，因此有可能会生成重复特性")]
    // [HarmonyPatch(typeof(WuLin.PlayerCreateManager), "GenerateSelectabelTraits")]
    // public class PlayerCreateManagerGenerateSelectabelTraits:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static List<GameData.TraitData> lst=new List<GameData.TraitData>();
    //     public static void Prefix(WuLin.PlayerCreateManager __instance){
    //         if (__instance.lockedTraitIndex>0 && __instance.lockedTraitIndex<__instance.selectableTraitDatas.Count) {
    //             for(int i=0;i<__instance.lockedTraitIndex;i++)lst.Append(__instance.selectableTraitDatas[i]);
    //         }
    //     }
    //     public static void Postfix(WuLin.PlayerCreateManager __instance){
    //         if (__instance.lockedTraitIndex>0 && __instance.lockedTraitIndex<__instance.selectableTraitDatas.Count) {
    //             for(int i=0;i<__instance.lockedTraitIndex && i<lst.Count;i++)__instance.selectableTraitDatas[i]=lst[i];
    //             lst.Clear();
    //         }
    //     }
    // }
    // [Desc("我的代码功底不足以令我不能拿到全traits","..")]
    // [HarmonyPatch(typeof(WuLin.PlayerCreateManager), "LockTraitByIndex")]
    // public class PlayerCreateManagerGenerateSelectabelTraits:Bstring{
    //     public static GameData.TraitDataScriptObject tso;
    //     public static string val;public void Init() {
    //         base.Init(ref val);
    //         if(this.Met(val)){
    //             tso=new GameData.TraitDataScriptObject();
    //             tso.GenerateData();
    //         }
    //     }
    //     public static void Postfix(WuLin.PlayerCreateManager __instance){
    //         if (val.Length>3) {
    //             int c=0;
    //             foreach (var t in val.Split('|')) {
    //                 GameData.TraitData td;
    //                 if (tso.nameDict.TryGetValue(t,out td)){
    //                     __instance.selectableTraitDatas[c]=td;
    //                     c++;
    //                 }
    //             }
    //         } else {
    //             foreach(var kv in tso.nameDict){
    //                 logger(kv.Key+":"+kv.Value.GetName(true));
    //             }
    //         }
    //     }
    // }
    // [Desc("制造trait时输出trait内容",0)] // release时应该设置为-1
    // [HarmonyPatch(typeof(WuLin.PlayerCreateManager), "CreateTraits")]
    // public class PlayerCreateManagerCreateTraits:Bbool{
    //     // public static int val;public void Init() {base.Init(ref val);}
    //     public static void Postfix(Il2CppSystem.Collections.Generic.List<GameData.TraitData> __result){
    //         __result.ForEach((Action<GameData.TraitData>)PlayerCreateManagerCreateTraits.log);
    //     }
    //     public static void log(GameData.TraitData trait){
    //         logger(trait.GetName(false)+"("+trait.GetName(true)+"): "+trait.GetInfo());
    //     }
    // }
//         [HarmonyPatch(typeof(Cheat), "Templates")]
//         class CheatTemplates : Bbool { // Bbool could be used directly
//
//         }
}

